﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;

namespace MyDLL
{
    /// <summary>
    /// 对文件夹和文件进行操作
    /// </summary>
    public class FilesAndDirectoriesUtility
    {
        /// <summary>
        /// 修改文件名后缀，并返回新的文件名。
        /// </summary>
        /// <param name="fileName">原文件名</param>
        /// <param name="newSuffix">新的后缀，注意不带“.”</param>
        /// <returns>返回新文件名</returns>
        public static string ModifyFileSuffix(string fileName, string newSuffix)
        {
            return StringUtility.ModifyFileSuffix(fileName, newSuffix);
        }

        /// <summary>
        /// 获取文件类型（不用FileInfo）。
        /// </summary>
        /// <param name="fileName">完整文件名</param>
        /// <returns>返回文件类型</returns>
        public static string GetFileType(string fileName)
        {
            return fileName.Substring(fileName.LastIndexOf('.') + 1, fileName.Length - fileName.LastIndexOf('.') - 1);
        }

        /// <summary>
        /// 判断文件类型是否为目标格式。
        /// </summary>
        /// <param name="fileName">完整文件名</param>
        /// <param name="fileType_Target">目标文件类型</param>
        /// <returns>返回bool值</returns>
        public static bool IsTargetFileFormat(string fileName, string fileType_Target)
        {
            bool retVal = true;
            string fileType = GetFileType(fileName);
            if (fileType != fileType_Target && fileType != fileType_Target.ToUpper() && fileType != fileType_Target.ToLower())
            {
                retVal = false;
            }
            return retVal;
        }

        /// <summary>
        /// 判断文件类型是否为目标格式（多个格式）。
        /// </summary>
        /// <param name="fileName">完整文件名</param>
        /// <param name="fileTypeArr_Target">目标文件类型数组</param>
        /// <returns>返回bool值</returns>
        public static bool IsTargetFileFormats(string fileName, string[] fileTypeArr_Target)
        {
            bool retVal = false;
            for (int i = 0; i < fileTypeArr_Target.Length; i++)
            {
                if (IsTargetFileFormat(fileName, fileTypeArr_Target[i]))
                {
                    retVal = true;
                    return retVal;
                }
            }
            return retVal;
        }

        /// <summary>
        /// 获取文件信息。
        /// </summary>
        /// <param name="filePath">文件完整路径</param>
        /// <returns>输出一个5个元素的字符串数组，分别是：文件名（0）、修改时间（1）、大小（2）、文件类型（3）、路径（4）。</returns>
        public static string[] GetFileInfo(string filePath)
        {
            string[] strArr = new string[5];
            /*  ================
             *  Index   内容
             *  ----------------
             *  0       文件名
             *  1       修改时间
             *  2       大小
             *  3       文件类型
             *  4       路径
             *  ================
             */

            //获取文件名
            FileInfo fileInfo = new FileInfo(filePath);
            strArr[0] = fileInfo.Name.ToString();
            strArr[1] = fileInfo.LastWriteTime.ToString();
            strArr[2] = Math.Ceiling(fileInfo.Length / 1024.0) + " KB";
            strArr[3] = fileInfo.Extension.ToString().Replace(".", string.Empty);
            strArr[4] = filePath;

            return strArr;
        }

        /// <summary>
        /// 获取一个文件夹下所有文件的文件名，并以字符串数组的形式返回。
        /// </summary>
        /// <param name="folderPath">母文件夹路径</param>
        /// <returns>返回字符串数组</returns>
        public static string[] GetFileNamesInOneFolder(string folderPath)
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(folderPath);
            FileInfo[] fileInfo = directoryInfo.GetFiles();
            string[] resArr = new string[fileInfo.Length];
            for (int i = 0; i < fileInfo.Length; i++)
            {
                resArr[i] = fileInfo[i].Name.ToString();
            }
            return resArr;
        }

        /// <summary>
        /// 获取一个文件夹下所有文件夹的名称，并以字符串数组的形式返回。
        /// </summary>
        /// <param name="folderPath">母文件夹路径</param>
        /// <returns>返回字符串数组</returns>
        public static string[] GetFolderNamesInOneFolder(string folderPath)
        {
            DirectoryInfo directoryInfo = new DirectoryInfo(folderPath);
            DirectoryInfo[] folderInfo = directoryInfo.GetDirectories();
            string[] resArr = new string[folderInfo.Length];
            for (int i = 0; i < folderInfo.Length; i++)
            {
                resArr[i] = folderInfo[i].Name.ToString();
            }
            return resArr;
        }

        /// <summary>
        /// 返回文件路径（不包括文件名）
        /// </summary>
        /// <param name="filePath">完整的文件名</param>
        /// <returns>返回文件路径（不包括文件名）</returns>
        public static string GetFilePath_ExcludingFileName(string filePath)
        {
            FileInfo fileInfo = new FileInfo(filePath);
            return filePath.Replace(fileInfo.Name, "");
        }

        /// <summary>
        /// 返回文件名（不包括文件路径）
        /// </summary>
        /// <param name="filePath">完整的文件名</param>
        /// <returns>返回文件名</returns>
        public static string GetFileName(string filePath)
        {
            FileInfo fileInfo = new FileInfo(filePath);
            return fileInfo.Name;
        }

        /// <summary>
        /// 将一个文件夹（包括文件夹、文件、子文件夹及子文件夹中的文件）复制到目标地址。
        /// </summary>
        /// <param name="path0">待复制的文件夹地址</param>
        /// <param name="pathDes">目标地址</param>
        public static void CopyFolderToNewDirectory_IncludingAllFiles(string path0,string pathDes)
        {
            //去掉path0、pathDes末尾的反斜杠
            string path0_N = DirectoryRemoveEndSlash(path0);
            string pathDes_N = DirectoryRemoveEndSlash(pathDes);

            //获取待复制文件夹名称
            string folder0Name = GetFolderName(path0_N);

            //在目标地址创建母文件夹
            pathDes_N += @"\" + folder0Name;
            Directory.CreateDirectory(pathDes_N);

            //如果待复制的文件夹地址存在，则开始复制
            if (Directory.Exists(path0_N))
            {
                //复制文件
                string[] files = Directory.GetFiles(path0_N);
                if(files.Length != 0)
                {
                    foreach (string f in files)
                    {
                        string fileName = Path.GetFileName(f);
                        string filePathDes = Path.Combine(pathDes_N, fileName);
                        File.Copy(f, filePathDes, true);//同名覆盖
                    }
                }

                //复制子文件夹
                string[] subFolders = Directory.GetDirectories(path0_N);
                foreach (string sf in subFolders)
                {
                    string sfName = GetFolderName(sf);
                    CopyFolderToNewDirectory_IncludingAllFiles(sf, pathDes_N);
                }
            }
        }

        /// <summary>
        /// 将一个文件夹（包括文件夹、文件、子文件夹及子文件夹中的文件）复制到目标地址，并修改母文件夹的名称。
        /// </summary>
        /// <param name="path0">待复制的文件夹地址</param>
        /// <param name="pathDes">目标地址</param>
        /// <param name="newFolderName">新的母文件夹名称</param>
        public static void CopyFolderToNewDirectoryAndChange1stFolderName_IncludingAllFiles(string path0, string pathDes,string newFolderName)
        {
            //去掉path0、pathDes末尾的反斜杠
            string path0_N = DirectoryRemoveEndSlash(path0);
            string pathDes_N = DirectoryRemoveEndSlash(pathDes);

            //在目标地址创建母文件夹
            pathDes_N += @"\" + newFolderName;
            Directory.CreateDirectory(pathDes_N);

            //如果待复制的文件夹地址存在，则开始复制
            if (Directory.Exists(path0_N))
            {
                //复制文件
                string[] files = Directory.GetFiles(path0_N);
                if (files.Length != 0)
                {
                    foreach (string f in files)
                    {
                        string fileName = Path.GetFileName(f);
                        string filePathDes = Path.Combine(pathDes_N, fileName);
                        File.Copy(f, filePathDes, true);//同名覆盖
                    }
                }

                //复制子文件夹
                string[] subFolders = Directory.GetDirectories(path0_N);
                foreach (string sf in subFolders)
                {
                    string sfName = GetFolderName(sf);
                    CopyFolderToNewDirectory_IncludingAllFiles(sf, pathDes_N);
                }
            }
        }

        /// <summary>
        /// 对一个文件夹（包括文件夹、文件、子文件夹及子文件夹中的文件）做处理后，复制到目标地址。
        /// </summary>
        /// <param name="path0">待处理的文件夹地址</param>
        /// <param name="pathDes">目标地址</param>
        /// <param name="action">
        /// 文件处理操作，该action委托传入一个完整的原文件路径和
        /// 一个不完整的目标文件路径（只有路径，没有文件名）。
        /// 该委托内需要有类似“File.Copy(f, filePathDes, true)”的文件复制操作。
        /// </param>
        public static void DoSmthgToFolderAndCopyToNewDirectory_IncludingAllFiles(string path0, string pathDes,System.Action<string,string> action)
        {
            //去掉path0、pathDes末尾的反斜杠
            string path0_N = DirectoryRemoveEndSlash(path0);
            string pathDes_N = DirectoryRemoveEndSlash(pathDes);

            //获取待复制文件夹名称
            string folder0Name = GetFolderName(path0_N);

            //在目标地址创建母文件夹
            pathDes_N += @"\" + folder0Name;
            Directory.CreateDirectory(pathDes_N);

            //如果待处理的文件夹地址存在，则开始处理
            if (Directory.Exists(path0_N))
            {
                //处理文件
                string[] files = Directory.GetFiles(path0_N);
                if (files.Length != 0)
                {
                    foreach (string f in files)
                    {
                        action(f, pathDes_N);//执行文件处理操作，包括复制文件。
                    }
                }

                //处理子文件夹
                string[] subFolders = Directory.GetDirectories(path0_N);
                foreach (string sf in subFolders)
                {
                    string sfName = GetFolderName(sf);
                    DoSmthgToFolderAndCopyToNewDirectory_IncludingAllFiles(sf, pathDes_N,action);
                }
            }
        }

        /// <summary>
        /// 对一个文件夹中的文件（包括各级子文件夹中的文件）做处理。
        /// </summary>
        /// <param name="path0">待处理的文件夹地址</param>
        /// <param name="action">
        /// 文件处理操作，该action委托传入一个完整的原文件路径。
        /// </param>
        public static void DoSmthgToFilesInFolder_IncludingAllFiles(string path0, System.Action<string> action)
        {
            //去掉path0的反斜杠
            string path0_N = DirectoryRemoveEndSlash(path0);

            //获取待复制文件夹名称
            string folder0Name = GetFolderName(path0_N);

            //如果待处理的文件夹地址存在，则开始处理
            if (Directory.Exists(path0_N))
            {
                //处理文件
                string[] files = Directory.GetFiles(path0_N);
                if (files.Length != 0)
                {
                    foreach (string f in files)
                    {
                        action(f);//执行文件处理操作。
                    }
                }

                //处理子文件夹
                string[] subFolders = Directory.GetDirectories(path0_N);
                foreach (string sf in subFolders)
                {
                    string sfName = GetFolderName(sf);
                    DoSmthgToFilesInFolder_IncludingAllFiles(sf, action);
                }
            }
        }

        /// <summary>
        /// 对一个文件夹（包括各级子文件夹，但不包括文件）做处理。
        /// </summary>
        /// <param name="path0">待处理的文件夹地址</param>
        /// <param name="action">
        /// 文件处理操作，传入一个待处理文件夹的完整路径（最后一个字符不是反斜杠）。
        /// </param>
        public static void DoSmthgToFolder_IncludingAllSubFolders(string path0, System.Action<string> action)
        {
            //去掉path0、pathDes末尾的反斜杠
            string path0_N = DirectoryRemoveEndSlash(path0);
            action(path0_N);

            //如果待处理的文件夹地址存在，则开始处理
            if (Directory.Exists(path0_N))
            {
                //处理子文件夹
                string[] subFolders = Directory.GetDirectories(path0_N);
                foreach (string sf in subFolders)
                {
                    string sfName = GetFolderName(sf);
                    DoSmthgToFolder_IncludingAllSubFolders(sf, action);
                }
            }
        }

        /// <summary>
        /// 去掉路径末尾的反斜杠。
        /// </summary>
        /// <param name="dir">路径</param>
        /// <returns>返回字符串</returns>
        public static string DirectoryRemoveEndSlash(string dir)
        {
            if (dir[dir.Length - 1].ToString() == @"\")
                return dir.Substring(0, dir.Length - 1);
            else
                return dir;
        }

        /// <summary>
        /// 在路径末尾添加反斜杠。
        /// </summary>
        /// <param name="dir">路径</param>
        /// <returns>返回字符串</returns>
        public static string DirectoryAddEndSlash(string dir)
        {
            if (dir[dir.Length - 1].ToString() == @"\")
                return dir;
            else
                return dir + @"\";
        }

        /// <summary>
        /// 获取路径上的全部母子文件夹名称，并返回字符串数组。
        /// </summary>
        /// <param name="dir">路径</param>
        /// <returns>返回字符串数组</returns>
        public static string[] GetFoldersNames(string dir)
        {
            string dir_N = DirectoryRemoveEndSlash(dir);
            string[,] resArr2D = Regex_Common.MatchCollection_Results("([^\\\\]+)", dir_N, new int[] { 0 });
            return BasicDataProcess_Common.GetColumnFrom2DArray<string>(resArr2D, 0);
        }

        /// <summary>
        /// 获取路径上最末级的文件夹名称，返回字符串。
        /// </summary>
        /// <param name="dir">路径</param>
        /// <returns>返回字符串</returns>
        public static string GetFolderName(string dir)
        {
            string[] resArr = GetFoldersNames(dir);
            return resArr[resArr.Length - 1];
        }
    }
}
